package com.xinyue.exceltool.logic;

import com.alibaba.fastjson.JSON;
import com.xinyue.exceltool.config.ExcelToolConfig;
import com.xinyue.exceltool.logic.convert.CellValueTypeStrategyEnum;
import com.xinyue.exceltool.logic.convert.ICellValueTypeStrategy;
import com.xinyue.exceltool.logic.model.ExcelClassData;
import com.xinyue.exceltool.logic.model.TitleCellData;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * excel配置数据转化为json，并输出到文件
 *
 * @author 王广帅
 * @since 2021/5/1 2:04 上午
 */
public class ExcelToServerJsonManager {
    private static Logger logger = LoggerFactory.getLogger(ExcelToServerJsonManager.class);
    private ExcelClassData excelClassData;
    private ExcelToolConfig excelToolConfig;

    private List<Map<String, Object>> rowDataMapCache = new ArrayList<>();
    private File writeJsonFile;


    public ExcelToServerJsonManager(ExcelClassData excelClassData, ExcelToolConfig excelToolConfig) {
        this.excelClassData = excelClassData;
        this.excelToolConfig = excelToolConfig;
        this.prepare();
    }

    private ICellValueTypeStrategy getValueConvert(String type) {
        return CellValueTypeStrategyEnum.getValueConvert(type);
    }

    private void checkAndMakeDir() {
        File dir = new File(excelToolConfig.getServerDataPath());
        //这里一定要先判断是否存在，如果不存在，不管是目录 ，还是文件，都是返回false
        if (dir.exists() && !dir.isDirectory()) {
            throw new IllegalArgumentException("服务器json文件目录配置错误:" + excelToolConfig.getServerDataPath());
        } else {
            dir.mkdir();
        }
    }


    private String getWriteJsonFilePath() {
        String path = excelToolConfig.getServerDataPath();
        if (!path.endsWith("/")) {
            path += "/";
        }
        path += getJsonFileName();
        return path;
    }

    /**
     * 获取生成的json文件的名字
     *
     * @return
     */
    private String getJsonFileName() {
        String[] splits = this.excelClassData.getFileName().split("\\.");
        String fileName = splits[0];
        //文件名首字母变大写
        fileName = StringUtils.capitalize(fileName);
        fileName = fileName.replace("_", "");
        fileName += ".json";
        return fileName;
    }


    private void prepare() {
        this.checkAndMakeDir();
        String jsonFilePath = getWriteJsonFilePath();
        writeJsonFile = new File(jsonFilePath);
        if (writeJsonFile.exists()) {
            writeJsonFile.delete();
        }
        try {
            writeJsonFile.createNewFile();
        } catch (Exception e) {
            logger.error("创建文件失败,文件路径:{}", writeJsonFile.getAbsolutePath(), e);
        }

    }

    public void appendRowDataToJsonFile(Map<Integer, String> rowData) {
        Map<String, Object> convertDataMap = new HashMap<>();
        rowData.forEach((colNum, value) -> {
            TitleCellData titleCellData = excelClassData.getTitleCellDataMap().get(colNum);
            if (titleCellData != null && titleCellData.isServerType() && value != null) {

                ICellValueTypeStrategy cellValueConvert = this.getValueConvert(titleCellData.getFieldType());
                Object result = cellValueConvert.convert(value);
                convertDataMap.put(titleCellData.getFieldName(), result);
            }
        });
        if (convertDataMap.size() > 0) {
            this.rowDataMapCache.add(convertDataMap);
            this.checkAndFlush();
        }
    }

    private void checkAndFlush() {
        if (this.rowDataMapCache.size() >= excelToolConfig.getDataFlushThreshold()) {
            forceFlush();
        }
    }

    public void forceFlush() {
        StringBuilder str = new StringBuilder();
        for (Map<String, Object> data : this.rowDataMapCache) {
            str.append(JSON.toJSONString(data)).append("\n");
        }
        try {
            appendToJsonFile(str.toString());
            this.rowDataMapCache.clear();
        } catch (Exception e) {
            logger.error("Excel数据写入json文件失败，文件名:{}", this.excelClassData.getFileName(), e);
        }
    }

    private void appendToJsonFile(String value) throws Exception {
        FileUtils.write(writeJsonFile, value, StandardCharsets.UTF_8, true);
    }


}
